#include "display.h"

osMutexId uart1Mutex;
osMutexDef(uart1Mutex);
unsigned char uart1DataResive[RESIVE_BUFF_SIZE]; //буфер для принимаемых по uatr1 данных
unsigned char kolDataUart1Resive;	 // кол- во данных принятых по 1 уарту	


void initDisplay()
{
		initPortDispay();
		initUart1();
		offDisplay();
		osDelay(100);	
		onDisplay();
		//resetDisplay();
		osDelay(TIME_START_DISPLAY);	
		uart1Mutex = osMutexCreate(osMutex(uart1Mutex));
		NVIC_EnableIRQ(USART1_IRQn); //активируем прерывание
}

void initPortDispay()
{
		GPIO_PortClock(PORT_DISPLAY_ON, ENABLE);		
	  GPIO_PinConfigure(PORT_DISPLAY_ON,PIN_DISPLAY_ON,GPIO_MODE_OUTPUT,GPIO_OUTPUT_PUSH_PULL, GPIO_OUTPUT_SPEED_100MHz,GPIO_NO_PULL_UP_DOWN);
		GPIO_PinAF (GPIOA,9,GPIO_AF_USART1);
		GPIO_PinAF (GPIOA,10,GPIO_AF_USART1);
		GPIO_PinConfigure(GPIOA,10,GPIO_MODE_AF,GPIO_OUTPUT_PUSH_PULL, GPIO_OUTPUT_SPEED_100MHz,GPIO_NO_PULL_UP_DOWN);
		GPIO_PinConfigure(GPIOA,9, GPIO_MODE_AF,GPIO_OUTPUT_PUSH_PULL, GPIO_OUTPUT_SPEED_100MHz,GPIO_NO_PULL_UP_DOWN);
		GPIO_PinConfigure(PORT_DISPLAY_RES,PIN_DISPLAY_RES,GPIO_MODE_OUTPUT,GPIO_OUTPUT_PUSH_PULL, GPIO_OUTPUT_SPEED_100MHz,GPIO_NO_PULL_UP_DOWN);
		GPIO_PinWrite(PORT_DISPLAY_RES,PIN_DISPLAY_RES,1);
	
	
}
void onDisplay()
{
	GPIO_PinWrite(PORT_DISPLAY_ON,PIN_DISPLAY_ON,1);
}

void resetDisplay()
{
	GPIO_PinWrite(PORT_DISPLAY_RES,PIN_DISPLAY_RES,0);
	osDelay(1);
	GPIO_PinWrite(PORT_DISPLAY_RES,PIN_DISPLAY_RES,1);
}

void initUart1()
{
	 RCC->APB2ENR MSET_BIT4 ;  		// подаём синхронизацию на uart1
	 USART1->CR1=0;
	 USART1->BRR= 0x2d9; 					// делитель 45.5625 8,6805 для скорости обмена 115200 на внутреннем тактирование 16 МГц !!! откудато 24 МГц
	 USART1->CR1 MSET_BIT13; 			// вкл уарт
	 USART1->CR1 MSET_BIT3;  			// ключить передачу
	 USART1->CR1 MSET_BIT2;  			// включить приём
	 USART1->CR1 MSET_BIT5;				// включить прерывание приёма данных
}

void offDisplay()
{
		GPIO_PinWrite(PORT_DISPLAY_ON,PIN_DISPLAY_ON,0);
}

void selectDisplay(SELECTION_SCREEN screen)
{	
	unsigned char buff[5]; // буфер для отсылки экрану 
	buff[0]=0x37; // стартовый байт
	switch (screen)
	{
		case START_SCREEN:
		{
				buff[1]=0x07; 
				buff[2]=0x37^0x07; 
				sendByteUart1(buff,3);
				break;
		}
		case MAIN_SCREEN:
		{
				buff[1]=0x03; 
				buff[2]=0x01;
				buff[3]=0x37^0x03^0x01;
				sendByteUart1(buff,4);
				break;
		}
		case RESULT_SCREEN:
		{
				buff[1]=0x03; 
				buff[2]=0x02; 
				buff[3]=0x37^0x03^0x02;
				sendByteUart1(buff,4);
				break;
		}
		case CONFIG_SCREEN:
		{
				buff[1]=0x03; 
				buff[2]=0x03; 
				buff[3]=0xdb;
				buff[4]=0xdc;
				sendByteUart1(buff,5);		
				break;
		}
		default:{}
	}
	
}
void setBattaryCharge(unsigned char kol)
{
		unsigned char buff[5]; // буфер для отсылки экрану
		unsigned short sizeBuff; // размер отправляемого буфера	
		if (kol>6) kol=0;
		sizeBuff=3; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x02; 
		buff[2]=kol; 
		buff[3]=calcCRC(buff,sizeBuff);
		sizeBuff++;
		scremble(buff,&sizeBuff);
		sendByteUart1(buff,sizeBuff);
}

void setTimeCountDown(unsigned char min, unsigned char sec)
{
		unsigned char buff[10]; // буфер для отсылки экрану 
		unsigned short sizeBuff; // размер отправляемого буфера
		if (min>30) min=30;
		if (sec>59) min=59;
		sizeBuff=4; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x05; 
		buff[2]=min; 
		buff[3]=sec;
		buff[4]=calcCRC(buff,sizeBuff);
		sizeBuff++;
		scremble(buff,&sizeBuff);	
		sendByteUart1(buff,sizeBuff);	
}

void setCountImpuls(unsigned short kol)
{
		unsigned char buff[8]; // буфер для отсылки экрану
		unsigned short sizeBuff; // размер отправляемого буфера	
	
		if (kol>999) kol=999;
		sizeBuff=4; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x06; 	
		buff[3]=(unsigned char )  kol&0xff;
		kol=kol>>8;
		buff[2]=(unsigned char)  kol&0xff; 		
		buff[4]=calcCRC(buff,sizeBuff);
		sizeBuff++;
		scremble(buff,&sizeBuff);
		sendByteUart1(buff,sizeBuff);	
}

void nopCommand()
{
		unsigned char buff[4]; // буфер для отсылки экрану
		buff[0]=0x37; // стартовый байт
		buff[1]=0x00; 
		buff[2]=0xbd; 
		buff[3]=0xdc; 
		sendByteUart1(buff,4);
}

void setDateTime(unsigned short year,unsigned char mon,
				 unsigned char day,unsigned char hour,unsigned char min)
{
	  unsigned char buff[18]; // буфер для отсылки экрану
		unsigned short sizeBuff; // размер отправляемого буфера	
		sizeBuff=9; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x01; 
		buff[2]=(unsigned char) ((unsigned short)year>>8);
		buff[3]=(unsigned char ) year&0xff;
		buff[4]=mon;
		buff[5]=day;	
		buff[6]=hour;
		buff[7]=min;
		buff[8]=00;	// секунды
		buff[9]=calcCRC(buff,sizeBuff);
		sizeBuff++;
		scremble(buff,&sizeBuff);
		sendByteUart1(buff,sizeBuff);		
}

void setParameter(PARAMETER_SELECTION parameter,unsigned short value)
{
  unsigned char buff[10]; // буфер для отсылки экрану
	unsigned short sizeBuff; // размер отправляемого буфера	
	sizeBuff=5; 
	switch (parameter)
	{
		case FILTER:
		{
				buff[0]=0x37; // стартовый байт
				buff[1]=0x04; 
				buff[2]=(unsigned char) ((unsigned short) value>>8); 
				buff[3]=(unsigned char )  value&0xff;
				buff[4]=parameter;
				buff[5]=calcCRC(buff,sizeBuff);
				sizeBuff++;
				scremble(buff,&sizeBuff);	
				sendByteUart1(buff,sizeBuff);	
				break;
		}
		case PERIOD_MEASURE:
		{
				buff[0]=0x37; // стартовый байт
				buff[1]=0x04; 
				buff[2]=(unsigned char) ((unsigned short) value>>8); 
				buff[3]=(unsigned char ) value&0xff; 
				buff[4]=parameter;
				buff[5]=calcCRC(buff,sizeBuff);
				sizeBuff++;
				scremble(buff,&sizeBuff);	
				sendByteUart1(buff,sizeBuff);	
				break;
		}
		default:{}
	}	
}

void sendKey(enum KeyStroke key,struct DataDisplay* resiveData)
{
		unsigned char buff[10]; // буфер для отсылки экрану 
		resiveData->params=NOT_PARAM;	
		switch (key)
		{
			case Left:
			{
					buff[0]=0x37; // стартовый байт
					buff[1]=0x08; 
					buff[2]=0x04; 
					buff[3]=0x37^0x08^0x04; 
					sendByteUart1(buff,4);
					break;
			}
			case Right:
			{
					buff[0]=0x37; // стартовый байт
					buff[1]=0x08; 
					buff[2]=0x05; 
					buff[3]=0x37^0x08^0x05; 
					sendByteUart1(buff,4);
					break;
			}
			case Down:
			{
					buff[0]=0x37; // стартовый байт
					buff[1]=0x08; 
					buff[2]=0x03; 
					buff[3]=0x37^0x08^0x03; 
					sendByteUart1(buff,4);
					break;
			}
			case Up:
			{
					buff[0]=0x37; // стартовый байт
					buff[1]=0x08; 
					buff[2]=0x02; 
					buff[3]=0x37^0x08^0x02; 
					sendByteUart1(buff,4);
					break;
			}
			case Esc:
			{
					buff[0]=0x37; // стартовый байт
					buff[1]=0x08; 
					buff[2]=0x00; 
					buff[3]=0x37^0x08^0x00; 
					sendByteUart1(buff,4);					
					break;
			}
			case Enter:
			{
					buff[0]=0x37; // стартовый байт
					buff[1]=0x08; 
					buff[2]=0x01; 
					buff[3]=0x37^0x08^0x01; 
					sendByteUart1(buff,4);				
					receivingDataUart1(resiveData); // возврат строки
					break;				
			}
		default:{}
	}	
}

void selectColumn(unsigned char column)
{
		unsigned char buff[10]; // буфер для отсылки экрану
		unsigned short sizeBuff; // размер отправляемого буфера	
		sizeBuff=3; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x09; 
		buff[2]=column; 
		buff[3]=calcCRC(buff,sizeBuff);
		sizeBuff++;
		scremble(buff,&sizeBuff);
		sendByteUart1(buff,sizeBuff);	
}

void sendStandBy(unsigned short sec,POWER_MODE_DISPLAY mode)
{
		unsigned char buff[10]; // буфер для отсылки экрану
		unsigned short sizeBuff; // размер отправляемого буфера	
		sizeBuff=5; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x0c; 
		buff[2]=(unsigned char)  ((unsigned short)sec>>8); 
		buff[3]=(unsigned char ) sec&0xff; 
		buff[4]=mode;
		buff[5]=calcCRC(buff,sizeBuff);	
		sizeBuff++;
		scremble(buff,&sizeBuff);
		sendByteUart1(buff,sizeBuff);	
}
void setProgressBar(unsigned char value)
{
	  unsigned char buff[10]; // буфер для отсылки экрану
		unsigned short sizeBuff; // размер отправляемого буфера	
		sizeBuff=3; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x0e; 
		buff[2]=value;
		buff[3]=calcCRC(buff,sizeBuff);	
		sizeBuff++;
		scremble(buff,&sizeBuff);
		sendByteUart1(buff,sizeBuff);		
}

void playWav(unsigned char numberWav, unsigned char volume)
{
		unsigned char buff[10]; // буфер для отсылки экрану
		unsigned short sizeBuff; // размер отправляемого буфера	
		sizeBuff=4; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x0f; 
		buff[2]=numberWav;
		buff[3]=volume;
		buff[4]=calcCRC(buff,sizeBuff);	
		sizeBuff++;
		scremble(buff,&sizeBuff);
		sendByteUart1(buff,sizeBuff);
}

void setBarGraph(unsigned short topAxis,unsigned short bottomAxis,unsigned char *pBar)
{
		unsigned char buff[140]; // буфер для отсылки экрану
		unsigned short sizeBuff; // размер отправляемого буфера	
		char i;
		sizeBuff=70; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x0A; 	
		buff[2]=(unsigned char) ((unsigned short)bottomAxis>>8);
		buff[3]=(unsigned char )  bottomAxis&0xff; 
		buff[4]=(unsigned char)  ((unsigned short)topAxis>>8); 
		buff[5]=(unsigned char ) topAxis&0xff;
		for(i=6;i<70;i++) 
		{		
				buff[i]=*pBar;
				pBar++;
		}
		buff[70]=calcCRC(buff,sizeBuff);
		sizeBuff++;
		scremble(buff,&sizeBuff);
		sendByteUart1(buff,sizeBuff);		
}

void setResultMeasure(unsigned short N1, unsigned short N2,float  N15,float b,CATEGORY_MASS stat1,CATEGORY_MASS stat2)
{
	  unsigned char buff[28]; 	// буфер для отсылки экрану
		unsigned short sizeBuff; 	// размер отправляемого буфера	
		unsigned short H_N15,H_b;	// целая и дробная часть 
		unsigned char L_N15,L_b;	// интенсивности и распределения
		H_N15=(unsigned short)N15;
		N15-=H_N15;
		N15*=100;
		L_N15=(unsigned char)N15;
	
		H_b=(unsigned short)b;
		b-=H_b;
		b*=100;
		L_b=(unsigned char)b;	
		sizeBuff=14; 
		buff[0]=0x37; // стартовый байт
		buff[1]=0x0b; 
		buff[2]=(unsigned char)  ((unsigned short)N1>>8); 
		buff[3]=(unsigned char ) N1&0xff; 
		buff[4]=(unsigned char)  ((unsigned short)N2>>8); 
		buff[5]=(unsigned char ) N2&0xff; 
		buff[6]=(unsigned char)  ((unsigned short)H_N15>>8); 
		buff[7]=(unsigned char ) H_N15&0xff; 
		buff[8]=(unsigned char)  ((unsigned short)H_b>>8); 
		buff[9]=(unsigned char ) H_b&0xff; 
		buff[10]=L_N15;
		buff[11]=L_b;
		buff[12]=stat1;
		buff[13]=stat2;
		buff[14]=calcCRC(buff,sizeBuff);	
		sizeBuff++;
		scremble(buff,&sizeBuff);
		sendByteUart1(buff,sizeBuff);	
	
}

void sendByteUart1(unsigned char *pData,unsigned short size)
{
		unsigned short i;
		osMutexWait(uart1Mutex, MAX_TIME_UART_WAIT); // занимаем мьютекс
		for(i=0;i<RESIVE_BUFF_SIZE;i++) // отчистка буфера приёма
		{
			uart1DataResive[kolDataUart1Resive]=0;
		}
		for (i=0;i<size;i++)
		{	
				while(!(USART1->SR & USART_SR_TC)){osThreadYield();}; //Ждем пока бит TC в регистре SR станет 1			
				USART1->DR=*pData;
				pData++;
		}
		kolDataUart1Resive=0;
		osMutexRelease(uart1Mutex);// освобождаем мьютекс
}



unsigned char calcCRC(unsigned char *pData,unsigned short sizeBuff)
{
		unsigned char crc=0;
		unsigned short i;
		for (i=0;i<sizeBuff;i++)
		{
			 crc^=*pData;
			 pData++;
		}
		return(crc);	
}
void scremble(unsigned char *pData,unsigned short *sizeBuff)
{
		unsigned short i=1,j;
		unsigned char *pTempData;
		pData++;// пропускаем символ начала кадра
		while(i<*sizeBuff)
		{
			if(*pData==0x37) // встретился символ начала кадра
			 {
					*pData=0xdb;
				 pTempData=pData+(*sizeBuff)-i; // адрес текущего конца буфера
				 for(j=i;j<*sizeBuff;j++)
					{
							*pTempData=*(pTempData-1);
							pTempData--;
							
					}
					pData++;
					*pData=0xdc;
					i++;
					*sizeBuff+=1;				
			 }
			if(*pData==0xdb) // встретился символ замены
			 {
				 *pData=0xdb;
				 pTempData=pData+(*sizeBuff)-i; // адрес текущего конца буфера
				 for(j=i;j<*sizeBuff;j++)
					{
							*pTempData=*(pTempData-1);
							pTempData--;
							
					}
					pData++;
					*pData=0xdd;
					i++;
					*sizeBuff+=1;			
			 }	
			 i++;	
			 pData++;
		}	
}

void receivingDataUart1(struct DataDisplay* resiveData)
{
	
		unsigned char i;
		osDelay(500); // задержка получения данных	
		resiveData->params=NOT_PARAM; // по умолчанию
		if (uart1DataResive[0]!=0x37) return; // выход если приняли не начало пакета
		if (uart1DataResive[1]!=0x04) return; // если нет ответа
		switch (uart1DataResive[3]) // номер параметра
		{
			case DATE_TIME: 			// дата время
			{			
					for(i=4;i<kolDataUart1Resive-1;i++)
					{
						switch(uart1DataResive[i])
						{
							case 0x42:
							{
								resiveData->data[i-4]=0x3a;
								break;
							}
							case 0x41:
							{
								resiveData->data[i-4]=0x2f;
								break;
							}
							case 0x40:
							{
								resiveData->data[i-4]=0x2e;
								break;
							}
							default:{resiveData->data[i-4]=uart1DataResive[i];}
						}
					}
					resiveData->params=DATE_TIME;
					break;
			}
			case FILTER: 					// значение фильтра
			{		
					resiveData->data[0]=uart1DataResive[5];
					resiveData->params=FILTER;
					break;
			}
			case PERIOD_MEASURE: // период иззмерения
			{					
					resiveData->data[0]=uart1DataResive[5];
					resiveData->params=PERIOD_MEASURE;
					break;
			}
			default:{resiveData->params=NOT_PARAM; }
		}				
}

void USART1_IRQHandler()
{
    //Проверяем, действительно ли прерывание вызвано приемом нового байта
				uart1DataResive[kolDataUart1Resive] = USART1->DR;		
				if (kolDataUart1Resive<RESIVE_BUFF_SIZE) kolDataUart1Resive++;			

}


